package analisis;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import utils.OS;

/**
 * @file EnrichNet.java
 * @author Juan Humanes Ferrer
 * @date 04-Marzo-2014
 */
public class EnrichNet {

    /**
     * Método que devuelve un String con lista de genes del fichero de entrada.
     * Se pasa por parametro la ruta del fichero.
     *
     * @param archivo
     * @return listaGenes
     */
    public static String crearAGS(String archivo) {
        String listaGenes = "";

        FileReader fr = null;
        BufferedReader br = null;

        try {
            // Apertura del fichero y creacion de BufferedReader para poder
            // hacer una lectura comoda (disponer del metodo readLine()).

            fr = new FileReader(archivo);
            br = new BufferedReader(fr);

            // Lectura del fichero
            int cont = 0;
            String linea;
            //Se le da el formato necesario para el script R
            while ((linea = br.readLine()) != null) {
                if (cont != 0) {
                    listaGenes += ",";
                }
                listaGenes += "\"" + linea + "\"";

                cont++;

            }
            listaGenes = listaGenes.substring(0, listaGenes.length());

        } catch (IOException e) {

        } finally {
            // En el finally cerramos el fichero, para asegurarnos
            // que se cierra tanto si todo va bien como si salta 
            // una excepcion.
            try {
                if (null != fr) {
                    fr.close();
                }
            } catch (IOException e2) {

            }
        }
        return listaGenes;

    }

    /**
     * Método que crea la variable network a partir de un sif con la red de
     * genes. Se pasa por parametro la ruta del fichero.
     *
     * @param archivo
     * @return network
     */
    public static String crearNetwork(String archivo) {
        String network = "";
        String[] linea2;

        FileReader fr = null;
        BufferedReader br = null;

        try {
            // Apertura del fichero y creacion de BufferedReader para poder
            // hacer una lectura comoda (disponer del metodo readLine()).

            fr = new FileReader(archivo);
            br = new BufferedReader(fr);

            // Lectura del fichero
            int cont = 0;
            String linea;
            while ((linea = br.readLine()) != null) {
                //Se le da el formato necesario para el Script R
                linea2 = linea.split(" ");
                if (linea2.length > 1) {
                    for (int i = 2; i < linea2.length; i++) {
                        network += "\"" + linea2[0] + " " + linea2[i] + "\"";
                        cont++;
                        //Se añade la coma entre genes
                        if (cont != 0) {
                            network += ",";
                        }
                    }
                }

            }
            //Se elimina la coma final
            network = network.substring(0, network.length() - 1);

        } catch (IOException e) {
        } finally {
            // En el finally cerramos el fichero, para asegurarnos
            // que se cierra tanto si todo va bien como si salta 
            // una excepcion.
            try {
                if (null != fr) {
                    fr.close();
                }
            } catch (IOException e2) {
            }
        }
        return network;

    }

    /**
     * Método que genera el script R que hace una llamada a NEA. Se pasa por
     * parametro:
     *
     * @param ficheroLista Lista de genes alterados
     * @param fgs Conjuntos de genes que describen sus actividades de genes
     * conocidos. Es necesario el formato de ags
     * @param fgslib La base de datos de anotación que proporciona información
     * detallada sobre las vías.
     * @param ficheroRed La red es un vector de pares de genes (dos símbolos de
     * genes con separación).
     * @param nperm Número de permutaciones
     * @param stat Puede tener dos valores: - FNEA depende del tamaño de AGS -
     * MNEA evita la dependencia centrandose en AGS
     * @param seed Numero de semillas
     * @param sesion Ruta donde se encuentran los ficheros del usuario
     * @return lista
     * @throws IOException
     * @throws InterruptedException
     */
    public static List<List> generarScript(String ficheroLista, String fgs, String fgslib,
            String ficheroRed, String nperm, String stat, String seed,
            String sesion) throws IOException, InterruptedException {
        String separator = OS.getDirectorySeparator();
        String barras = OS.getDoubleDirectorySeparator();
        String raiz = OS.getR();
        List<List> lista = null;
        String ags = crearAGS(ficheroLista);
        String network = crearNetwork(ficheroRed);
        File directorio = new File(sesion);

        //int pos = sesion.lastIndexOf(separator);
        //String r = sesion.substring(0, pos);
        //pos = r.lastIndexOf(separator);
        //r = r.substring(0, pos);

        if (directorio.mkdir()) {
        }

        File script = new File(sesion + separator + "script.R");
        script.createNewFile();

        File salida = new File(sesion + separator + "res.txt");
        salida.createNewFile();

        File salida2 = new File(sesion + separator + "resb.txt");
        salida2.createNewFile();

        File salida3 = new File(sesion + separator + "resc.txt");
        salida3.createNewFile();

        File salida4 = new File(sesion + separator + "resd.txt");
        salida4.createNewFile();

        File salida5 = new File(sesion + separator + "rese.txt");
        salida5.createNewFile();

        File salida6 = new File(sesion + separator + "resf.txt");
        salida6.createNewFile();

        File salida7 = new File(sesion + separator + "resg.txt");
        salida7.createNewFile();
        
        File salida8 = new File(sesion + separator + "resh.txt");
        salida8.createNewFile();

        PrintWriter pwScript;
        try (FileWriter scriptW = new FileWriter(sesion + separator + "script.R")) {
            pwScript = new PrintWriter(scriptW);
            pwScript.flush();
            pwScript.println("library(tcltk)");
            pwScript.flush();
            pwScript.flush();
            pwScript.println("library(neaGUI)");
            pwScript.flush();
            //Crear una variable en r con la lista de genes
            pwScript.flush();
            pwScript.println("AGS<-c(" + ags + ")");
            pwScript.flush();
            //Crear una variable en R con la red
            pwScript.flush();
            pwScript.println("NETWORK<-c(" + network + ")");
            pwScript.flush();
            //LLamada a nea
            pwScript.flush();
            pwScript.println("res <- nea(ags=AGS, fgs = \"" + fgs + "\", fgslib = \"" + fgslib + "\""
                    + ", network=NETWORK, pnet = NULL, nperm = " + nperm + ", stat=\"" + stat + "\", seed = " + seed + ")");
            pwScript.flush();
            pwScript.flush();
            pwScript.println("x<-res$MainResult");
            pwScript.flush();
            String sesionR = "";
            String[] linea2 = sesion.split(barras);
            for (int i = 0; i < linea2.length; i++) {
                if (i < linea2.length - 1) {
                    sesionR += linea2[i] + barras;

                } else {
                    sesionR += linea2[i];
                }

            }   //Pasar el resultado a un fichero
            pwScript.flush();
            pwScript.println("write(t(x[1]),\"" + sesionR + barras + "res.txt\",ncol=ncol(x))");
            pwScript.flush();
            int i;
            switch (fgs) {
                case "Reactome":
                    i=2;
                    break;
                default :
                    i=3;
                    break;
            }

            pwScript.flush();
            pwScript.println("write(t(x["+i+"]),\"" + sesionR + barras + "resb.txt\",ncol=ncol(x))");
            pwScript.flush();
            
            i++;

            pwScript.flush();
            pwScript.println("write(t(x["+i+"]),\"" + sesionR + barras + "resc.txt\",ncol=ncol(x))");
            pwScript.flush();
            
            i++;

            pwScript.flush();
            pwScript.println("write(t(x["+i+"]),\"" + sesionR + barras + "resd.txt\",ncol=ncol(x))");
            pwScript.flush();
            
            i++;

            pwScript.flush();
            pwScript.println("write(t(x["+i+"]),\"" + sesionR + barras + "rese.txt\",ncol=ncol(x))");
            pwScript.flush();
            
            i++;

            pwScript.flush();
            pwScript.println("write(t(x["+i+"]),\"" + sesionR + barras + "resf.txt\",ncol=ncol(x))");
            pwScript.flush();
            
            i++;

            pwScript.flush();
            pwScript.println("write(t(x["+i+"]),\"" + sesionR + barras + "resg.txt\",ncol=ncol(x))");
            pwScript.flush();
            
            i++;
            
            pwScript.flush();
            pwScript.println("write(t(x["+i+"]),\"" + sesionR + barras + "resh.txt\",ncol=ncol(x))");
            pwScript.flush();
        }
        pwScript.close();

        /*Se pasa por parámetro la ruta donde se encuentra el ejecutable de R y el archivo .R 
         a ejecutar (sesion)*/
        Process p = Runtime.getRuntime().exec(raiz + sesion + separator + "script.R");
        p.waitFor();

        String archivo = sesion + separator + "res";
        lista = listaEnriquecimiento(archivo);

        return lista;

    }

    /**
     * Método que se le pasa por parametro el archivo con los resultados de NEA
     * creado en el script y lo transforma a una lista con los resultados en
     * cada pathway
     *
     * @param archivo
     * @return lista
     */
    public static List<List> listaEnriquecimiento(String archivo) {

        FileReader fr1 = null;
        BufferedReader br1 = null;
        FileReader fr2 = null;
        BufferedReader br2 = null;
        FileReader fr3 = null;
        BufferedReader br3 = null;
        FileReader fr4 = null;
        BufferedReader br4 = null;
        FileReader fr5 = null;
        BufferedReader br5 = null;
        FileReader fr6 = null;
        BufferedReader br6 = null;
        FileReader fr7 = null;
        BufferedReader br7 = null;
        FileReader fr8 = null;
        BufferedReader br8 = null;
        String[] lista1;
        String archivo1 = archivo + ".txt";
        String[] lista2;
        String archivo2 = archivo + "b.txt";
        String[] lista3;
        String archivo3 = archivo + "c.txt";
        String[] lista4;
        String archivo4 = archivo + "d.txt";
        String[] lista5;
        String archivo5 = archivo + "e.txt";
        String[] lista6;
        String archivo6 = archivo + "f.txt";
        String[] lista7;
        String archivo7 = archivo + "g.txt";
        String[] lista8;
        String archivo8 = archivo + "h.txt";
        List<List> lista = new ArrayList();

        try {
            // Apertura del fichero y creacion de BufferedReader para poder
            // hacer una lectura comoda (disponer del metodo readLine()).

            fr1 = new FileReader(archivo1);
            br1 = new BufferedReader(fr1);
            fr2 = new FileReader(archivo2);
            br2 = new BufferedReader(fr2);
            fr3 = new FileReader(archivo3);
            br3 = new BufferedReader(fr3);
            fr4 = new FileReader(archivo4);
            br4 = new BufferedReader(fr4);
            fr5 = new FileReader(archivo5);
            br5 = new BufferedReader(fr5);
            fr6 = new FileReader(archivo6);
            br6 = new BufferedReader(fr6);
            fr7 = new FileReader(archivo7);
            br7 = new BufferedReader(fr7);
            fr8 = new FileReader(archivo8);
            br8 = new BufferedReader(fr8);
            String linea1;
            String linea2;
            String linea3;
            String linea4;
            String linea5;
            String linea6;
            String linea7;
            String linea8;
            while ((linea1 = br1.readLine()) != null) {

                
                linea2 = br2.readLine();
                linea3 = br3.readLine();
                linea4 = br4.readLine();
                linea5 = br5.readLine();
                linea6 = br6.readLine();
                linea7 = br7.readLine();
                linea8 = br8.readLine();
                lista1 = linea1.split(" ");
                lista2 = linea2.split(" ");
                lista3 = linea3.split(" ");
                lista4 = linea4.split(" ");
                lista5 = linea5.split(" ");
                lista6 = linea6.split(" ");
                lista7 = linea7.split(" ");
                lista8 = linea8.split(" ");

                for (int i = 0; i < lista1.length; i++) {
                    List<String> listaF = new ArrayList();
                    listaF.add(lista1[i]);
                    listaF.add(lista2[i]);
                    listaF.add(lista3[i]);
                    listaF.add(lista4[i]);
                    listaF.add(lista5[i]);
                    listaF.add(lista6[i]);
                    listaF.add(lista7[i]);
                    listaF.add(lista8[i]);
                    lista.add(listaF);
                }
                

            }

            

        } catch (IOException e) {

        } finally {
            // En el finally cerramos el fichero, para asegurarnos
            // que se cierra tanto si todo va bien como si salta 
            // una excepcion.
            try {
                if (null != fr1) {
                    fr1.close();
                    fr2.close();
                    fr3.close();
                    fr4.close();
                    fr5.close();
                    fr6.close();
                    fr7.close();
                    fr8.close();
                }
                
            } catch (IOException e2) {

            }
        }
        return lista;
    }

}
